package top.codef.persist.contributors;

import javax.money.MonetaryAmount;

import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.descriptor.jdbc.BigIntJdbcType;
import org.hibernate.type.descriptor.jdbc.DecimalJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.VarcharJdbcType;
import org.javamoney.moneta.FastMoney;
import org.javamoney.moneta.Money;
import org.javamoney.moneta.RoundedMoney;

import top.codef.money.interfaces.MercuryMonetaryAmountFormat;
import top.codef.persist.basictypes.FastMoneyType;
import top.codef.persist.basictypes.MonetaMoneyType;
import top.codef.persist.basictypes.RoundedMoneyType;
import top.codef.persist.descriptors.MonetaryTypeDescriptor;
import top.codef.properties.MercuryPersistProperties;

public class MonetaryTypeContributor implements TypeContributor {

	private final MercuryPersistProperties mercuryPersistProperties;

	private final MercuryMonetaryAmountFormat mercuryMonetaryAmountFormat;

	public MonetaryTypeContributor(MercuryPersistProperties mercuryPersistProperties,
			MercuryMonetaryAmountFormat mercuryMonetaryAmountFormat) {
		this.mercuryPersistProperties = mercuryPersistProperties;
		this.mercuryMonetaryAmountFormat = mercuryMonetaryAmountFormat;
	}

	@Override
	public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
		JdbcType sqlTypeDescriptor = confirmSqlType();
		MonetaryTypeDescriptor<FastMoney> fastMoneyTypeDescriptor = new MonetaryTypeDescriptor<>(FastMoney.class,
				mercuryPersistProperties, mercuryMonetaryAmountFormat);
		MonetaryTypeDescriptor<RoundedMoney> roundedMoneyTypeDescriptor = new MonetaryTypeDescriptor<>(
				RoundedMoney.class, mercuryPersistProperties, mercuryMonetaryAmountFormat);
		MonetaryTypeDescriptor<Money> moneyTypeDescriptor = new MonetaryTypeDescriptor<>(Money.class,
				mercuryPersistProperties, mercuryMonetaryAmountFormat);
		BasicTypeRegistry basicTypeRegistry = typeContributions.getTypeConfiguration().getBasicTypeRegistry();
		FastMoneyType fastMoneyType = new FastMoneyType(sqlTypeDescriptor, fastMoneyTypeDescriptor);
		RoundedMoneyType roundedMoneyType = new RoundedMoneyType(sqlTypeDescriptor, roundedMoneyTypeDescriptor);
		MonetaMoneyType monetaMoneyType = new MonetaMoneyType(sqlTypeDescriptor, moneyTypeDescriptor);
		basicTypeRegistry.register(fastMoneyType,
				new String[] { MonetaryAmount.class.getName(), FastMoney.class.getName() });
		basicTypeRegistry.register(roundedMoneyType, new String[] { RoundedMoney.class.getName() });
		basicTypeRegistry.register(monetaMoneyType, new String[] { Money.class.getName() });
	}

	private JdbcType confirmSqlType() {
		switch (mercuryPersistProperties.getMoneyDataType()) {
		case BIGINT:
			return BigIntJdbcType.INSTANCE;
		case DECIMAL:
			return DecimalJdbcType.INSTANCE;
		case VARCHAR:
			return VarcharJdbcType.INSTANCE;
		}
		// TODO 这里埋个伏笔
		return null;
	}
}
